using System.Collections.Generic;
using System.IO;
using Unity.Entities;
using UnityEngine;

// ReSharper disable once CheckNamespace
public partial class AssetLoadSystem : SystemBase
{
    private readonly List<ResData> resDatas = new List<ResData>();
    private struct ResData
    {
        public Unity.Scenes.ReferencedUnityObjects refs;
        public TextAsset bytesAsset;
        public Entity entity;
        public string path;
    }
    private readonly Dictionary<string, Entity> assetCached = new Dictionary<string, Entity>();
    private static readonly List<Entity> linkedEntities = new List<Entity>();
    
    protected override void OnUpdate()
    {
        resDatas.Clear();
        
        foreach (var (request, entity) in SystemAPI.Query<RefRO<AssetLoadRequest>>().WithEntityAccess())
        {
            string path = request.ValueRO.path.ToString();

            ResData prototype = new ResData()
            {
                entity = entity,
                path = path
            };
            if (assetCached.ContainsKey(path))
            {
                resDatas.Add(prototype);
                continue;
            }
            
            TextAsset bytesAsset = AssetAdapter.Load<TextAsset>(path + ".bytes");
            
            Unity.Scenes.ReferencedUnityObjects refs =
                AssetAdapter.Load<Unity.Scenes.ReferencedUnityObjects>(path + ".asset");

            prototype.refs = refs;
            prototype.bytesAsset = bytesAsset;
            if (bytesAsset == null)
            {
                Debug.LogError($"Fail to load bytes asset: {path}");
                continue;
            }
            resDatas.Add(prototype);
        }

        for (int i = 0; i < resDatas.Count; ++i)
        {
            ResData data = resDatas[i];

            if (!assetCached.TryGetValue(data.path, out Entity asset))
            {
                asset = SerializeTool.Deserialize(data.bytesAsset.bytes, data.refs, EntityManager);

                linkedEntities.Add(asset);
                if (EntityManager.HasBuffer<LinkedEntityGroup>(asset))
                {
                    DynamicBuffer<LinkedEntityGroup> linkedEntityGroups = EntityManager.GetBuffer<LinkedEntityGroup>(asset);
                    for (int c = 0; c < linkedEntityGroups.Length; ++c)
                    {
                        LinkedEntityGroup group = linkedEntityGroups[c];
                        linkedEntities.Add(group.Value);
                    }
                }

                foreach (var e in linkedEntities)
                {
                    EntityManager.AddComponentData(e, new Prefab());
                }
                linkedEntities.Clear();
                
                EntityManager.SetName(asset, "Prefab&" + Path.GetFileNameWithoutExtension(data.path));
                assetCached.Add(data.path, asset);
            }
            
            EntityManager.RemoveComponent<AssetLoadRequest>(data.entity);
            EntityManager.AddComponentData(data.entity, new AssetLoadResult()
            {
                asset = asset
            });
        }
    }
}